home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / MFCPixelShader / pixelshader.cpp < prev    next >
C/C++ Source or Header  |  2001-10-31  |  26KB  |  807 lines

  1. //-----------------------------------------------------------------------------
  2. // File: PixelShader.cpp
  3. //
  4. // Desc: Example code showing how to use pixel shaders in D3D
  5. //
  6. // Copyright (c) 1997-2001 Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #include "stdafx.h"
  10. #include <tchar.h>
  11. #include <math.h>
  12. #include <time.h>
  13. #include <stdio.h>
  14. #include <D3DX8.h>
  15. #include "resource.h"
  16. #include "D3DApp.h"
  17. #include "D3DUtil.h"
  18. #include "DXUtil.h"
  19. #include "PixelShader.h"
  20.  
  21.  
  22.  
  23.  
  24. //-----------------------------------------------------------------------------
  25. // Global data and objects
  26. //-----------------------------------------------------------------------------
  27. CApp          g_App;
  28. CAppForm*     g_AppFormView = NULL;
  29. TCHAR*        g_strAppTitle = _T("MFCPixelShader");
  30.  
  31.  
  32.  
  33.  
  34. //-----------------------------------------------------------------------------
  35. // The MFC macros are all listed here
  36. //-----------------------------------------------------------------------------
  37. IMPLEMENT_DYNCREATE( CAppDoc,      CDocument )
  38. IMPLEMENT_DYNCREATE( CAppFrameWnd, CFrameWnd )
  39. IMPLEMENT_DYNCREATE( CAppForm,     CFormView )
  40.  
  41.  
  42. BEGIN_MESSAGE_MAP( CApp, CWinApp )
  43.     //{{AFX_MSG_MAP(CD3DApp)
  44.     //}}AFX_MSG_MAP
  45. END_MESSAGE_MAP()
  46.  
  47.  
  48. BEGIN_MESSAGE_MAP( CAppForm, CFormView )
  49.     //{{AFX_MSG_MAP(CAppForm)
  50.     ON_WM_HSCROLL()
  51.     ON_COMMAND(    IDC_VIEWFULLSCREEN,       OnToggleFullScreen )
  52.     ON_COMMAND(    IDM_CHANGEDEVICE,         OnChangeDevice )
  53.     ON_BN_CLICKED( IDC_OPEN,                 OnOpenPixelShaderFile )
  54.     ON_BN_CLICKED( IDC_PRESET_0,             OnPresets )
  55.     ON_BN_CLICKED( IDC_PRESET_1,             OnPresets )
  56.     ON_BN_CLICKED( IDC_PRESET_2,             OnPresets )
  57.     ON_BN_CLICKED( IDC_PRESET_3,             OnPresets )
  58.     ON_BN_CLICKED( IDC_PRESET_4,             OnPresets )
  59.     ON_BN_CLICKED( IDC_PRESET_5,             OnPresets )
  60.     ON_EN_CHANGE(  IDC_INSTRUCTIONS,         OnChangeInstructions )
  61.     //}}AFX_MSG_MAP
  62. END_MESSAGE_MAP()
  63.  
  64.  
  65.  
  66.  
  67. BEGIN_MESSAGE_MAP(CAppDoc, CDocument)
  68.     //{{AFX_MSG_MAP(CAppDoc)
  69.         // NOTE - the ClassWizard will add and remove mapping macros here.
  70.         //    DO NOT EDIT what you see in these blocks of generated code!
  71.     //}}AFX_MSG_MAP
  72. END_MESSAGE_MAP()
  73.  
  74.  
  75.  
  76.  
  77. BEGIN_MESSAGE_MAP(CAppFrameWnd, CFrameWnd)
  78.     //{{AFX_MSG_MAP(CAppFrameWnd)
  79.     //}}AFX_MSG_MAP
  80. END_MESSAGE_MAP()
  81.  
  82.  
  83.  
  84.  
  85. //-----------------------------------------------------------------------------
  86. // Function prototypes and global (or static) variables
  87. //-----------------------------------------------------------------------------
  88. struct CUSTOMVERTEX
  89. {
  90.     FLOAT x, y, z;
  91.     DWORD color1, color2;
  92.     FLOAT tu1, tv1;
  93.     FLOAT tu2, tv2;
  94. };
  95.  
  96. #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_SPECULAR|D3DFVF_TEX2)
  97.  
  98. static CUSTOMVERTEX g_Vertices[]=
  99. {
  100.     // Color 0 (diffuse) is a color gradient
  101.     // Color 1 (specular) is a greyscale ramp
  102.     //  x      y     z     diffuse     specular    u1    v1    u2    v2
  103.     { -1.0f, -1.0f, 0.0f, 0xff00ffff, 0xffffffff, 1.0f, 1.0f, 1.0f, 1.0f },
  104.     { +1.0f, -1.0f, 0.0f, 0xffffff00, 0xffffffff, 0.0f, 1.0f, 0.0f, 1.0f },
  105.     { +1.0f, +1.0f, 0.0f, 0xffff0000, 0xff000000, 0.0f, 0.0f, 0.0f, 0.0f },
  106.     { -1.0f, +1.0f, 0.0f, 0xff0000ff, 0xff000000, 1.0f, 0.0f, 1.0f, 0.0f },
  107. };
  108.  
  109. inline DWORD FtoDW( FLOAT f ) { return *((DWORD*)&f); }
  110.  
  111.  
  112.  
  113. //-----------------------------------------------------------------------------
  114. // Name: AdjustWindowForChange()
  115. // Desc: Adjusts the window properties for windowed or fullscreen mode
  116. //-----------------------------------------------------------------------------
  117. HRESULT CAppForm::AdjustWindowForChange()
  118. {
  119.     if( m_bWindowed )
  120.     {
  121.         ::ShowWindow( m_hwndRenderFullScreen, SW_HIDE );
  122.         CD3DApplication::m_hWnd = m_hwndRenderWindow;
  123.     }
  124.     else
  125.     {
  126.         if( ::IsIconic( m_hwndRenderFullScreen ) )
  127.             ::ShowWindow( m_hwndRenderFullScreen, SW_RESTORE );
  128.         ::ShowWindow( m_hwndRenderFullScreen, SW_SHOW );
  129.         CD3DApplication::m_hWnd = m_hwndRenderFullScreen;
  130.     }
  131.     return S_OK;
  132. }
  133.  
  134.  
  135.  
  136.  
  137. //-----------------------------------------------------------------------------
  138. // Name: FullScreenWndProc()
  139. // Desc: The WndProc funtion used when the app is in fullscreen mode. This is
  140. //       needed simply to trap the ESC key.
  141. //-----------------------------------------------------------------------------
  142. LRESULT CALLBACK FullScreenWndProc( HWND hWnd, UINT msg, WPARAM wParam,
  143.                                     LPARAM lParam )
  144. {
  145.     if( msg == WM_CLOSE )
  146.     {
  147.         // User wants to exit, so go back to windowed mode and exit for real
  148.         g_AppFormView->OnToggleFullScreen();
  149.         g_App.GetMainWnd()->PostMessage( WM_CLOSE, 0, 0 );
  150.     }
  151.  
  152.     if( msg == WM_SETCURSOR )
  153.     {
  154.         SetCursor( NULL );
  155.     }
  156.  
  157.     if( msg == WM_KEYUP && wParam == VK_ESCAPE )
  158.     {
  159.         // User wants to leave fullscreen mode
  160.         g_AppFormView->OnToggleFullScreen();
  161.     }
  162.  
  163.     return DefWindowProc( hWnd, msg, wParam, lParam );
  164. }
  165.  
  166.  
  167.  
  168.  
  169. //-----------------------------------------------------------------------------
  170. // Name: CheckForLostFullscreen()
  171. // Desc: If fullscreen and device was lost (probably due to alt-tab), 
  172. //       automatically switch to windowed mode
  173. //-----------------------------------------------------------------------------
  174. HRESULT CAppForm::CheckForLostFullscreen()
  175. {
  176.     HRESULT hr;
  177.  
  178.     if( m_bWindowed )
  179.         return S_OK;
  180.  
  181.     if( FAILED( hr = m_pd3dDevice->TestCooperativeLevel() ) )
  182.         ForceWindowed();
  183.  
  184.     return S_OK;
  185. }
  186.  
  187.  
  188.  
  189.  
  190. //-----------------------------------------------------------------------------
  191. // Name: PreCreateWindow()
  192. // Desc: Change the window style (so it cannot maximize or be sized) before
  193. //       the main frame window is created.
  194. //-----------------------------------------------------------------------------
  195. BOOL CAppFrameWnd::PreCreateWindow( CREATESTRUCT& cs )
  196. {
  197.     cs.style = WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX;
  198.  
  199.     return CFrameWnd::PreCreateWindow( cs );
  200. }
  201.  
  202.  
  203.  
  204.  
  205. //-----------------------------------------------------------------------------
  206. // Name: InitInstance()
  207. // Desc: This is the main entry point for the application. The MFC window stuff
  208. //       is initialized here. See also the main initialization routine for the
  209. //       CAppForm class, which is called indirectly from here.
  210. //-----------------------------------------------------------------------------
  211. BOOL CApp::InitInstance()
  212. {
  213.     // Asscociate the MFC app with the frame window and doc/view classes
  214.     AddDocTemplate( new CSingleDocTemplate( IDR_MAINFRAME, 
  215.                                             RUNTIME_CLASS(CAppDoc),
  216.                                             RUNTIME_CLASS(CAppFrameWnd),
  217.                                             RUNTIME_CLASS(CAppForm) ) );
  218.  
  219.     // Dispatch commands specified on the command line (req'd by MFC). This
  220.     // also initializes the the CAppDoc, CAppFrameWnd, and CAppForm classes.
  221.     CCommandLineInfo cmdInfo;
  222.     ParseCommandLine( cmdInfo );
  223.     if( !ProcessShellCommand( cmdInfo ) )
  224.         return FALSE;
  225.  
  226.     if( !g_AppFormView->IsReady() )
  227.         return FALSE;
  228.  
  229.     g_AppFormView->GetParentFrame()->RecalcLayout();
  230.     g_AppFormView->ResizeParentToFit( FALSE ); 
  231.     
  232.     m_pMainWnd->SetWindowText( g_strAppTitle );
  233.     m_pMainWnd->UpdateWindow();
  234.  
  235.     return TRUE;
  236. }
  237.  
  238.  
  239.  
  240.  
  241. //-----------------------------------------------------------------------------
  242. // Name: OnIdle()
  243. // Desc: Uses idle time to render the 3D scene.
  244. //-----------------------------------------------------------------------------
  245. BOOL CApp::OnIdle( LONG )
  246. {
  247.     // Do not render if the app is minimized
  248.     if( m_pMainWnd->IsIconic() )
  249.         return FALSE;
  250.  
  251.     // Update and render a frame
  252.     if( g_AppFormView->IsReady() )
  253.     {
  254.         g_AppFormView->CheckForLostFullscreen();
  255.         g_AppFormView->RenderScene();
  256.     }
  257.  
  258.     // Keep requesting more idle time
  259.     return TRUE;
  260. }
  261.  
  262.  
  263.  
  264.  
  265. //-----------------------------------------------------------------------------
  266. // Name: CAppForm()
  267. // Desc: Constructor for the dialog resource form
  268. //-----------------------------------------------------------------------------
  269. CAppForm::CAppForm()
  270.          :CFormView( IDD_FORMVIEW )
  271. {
  272.     g_AppFormView     = this;
  273.  
  274.     m_pTexture0       = NULL;
  275.     m_pTexture1       = NULL;
  276.     m_pQuadVB         = NULL;
  277.     m_hPixelShader    = NULL;
  278.     m_pD3DXBufShader  = NULL;
  279. }
  280.  
  281.  
  282.  
  283.  
  284. //-----------------------------------------------------------------------------
  285. // Name: ~CAppForm()
  286. // Desc: Destructor for the dialog resource form. Shuts down the app
  287. //-----------------------------------------------------------------------------
  288. CAppForm::~CAppForm()
  289. {
  290.     Cleanup3DEnvironment();
  291. }
  292.  
  293.  
  294.  
  295.  
  296. //-----------------------------------------------------------------------------
  297. // Name: OnInitialUpdate()
  298. // Desc: When the AppForm object is created, this function is called to
  299. //       initialize it. Here we getting access ptrs to some of the controls,
  300. //       and setting the initial state of some of them as well.
  301. //-----------------------------------------------------------------------------
  302. VOID CAppForm::OnInitialUpdate()
  303. {
  304.     CFormView::OnInitialUpdate();
  305.  
  306.     // Save static reference to the render window
  307.     m_hwndRenderWindow = GetDlgItem(IDC_RENDERVIEW)->GetSafeHwnd();
  308.  
  309.     // Register a class for a fullscreen window
  310.     WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW, FullScreenWndProc, 0, 0, NULL,
  311.                           NULL, NULL, (HBRUSH)GetStockObject(WHITE_BRUSH), NULL,
  312.                           _T("Fullscreen Window") };
  313.     RegisterClass( &wndClass );
  314.  
  315.     // We create the fullscreen window (not visible) at startup, so it can
  316.     // be the focus window.  The focus window can only be set at CreateDevice
  317.     // time, not in a Reset, so ToggleFullscreen wouldn't work unless we have
  318.     // already set up the fullscreen focus window.
  319.     m_hwndRenderFullScreen = CreateWindow( _T("Fullscreen Window"), NULL,
  320.                                            WS_POPUP, CW_USEDEFAULT,
  321.                                            CW_USEDEFAULT, 100, 100,
  322.                                            GetTopLevelParent()->GetSafeHwnd(), 0L, NULL, 0L );
  323.  
  324.     // Note that for the MFC samples, the device window and focus window
  325.     // are not the same.
  326.     CD3DApplication::m_hWnd = m_hwndRenderWindow;
  327.     CD3DApplication::m_hWndFocus = m_hwndRenderFullScreen;
  328.     CD3DApplication::Create( AfxGetInstanceHandle() );
  329.  
  330.     // Set up the form's UI
  331.     ((CButton*)GetDlgItem(IDC_PRESET_0))->SetCheck(TRUE);
  332.     OnPresets();
  333. }
  334.  
  335.  
  336.  
  337.  
  338. //-----------------------------------------------------------------------------
  339. // Name: SetPixelShader()
  340. // Desc:
  341. //-----------------------------------------------------------------------------
  342. HRESULT CAppForm::SetPixelShader( TCHAR* strOpcodes )
  343. {
  344.     HRESULT      hr;
  345.     LPD3DXBUFFER pBuffer = NULL;
  346.  
  347.     SAFE_RELEASE( m_pD3DXBufShader );
  348.  
  349.     // Build a DWORD array of opcodes from the text string
  350.     hr = D3DXAssembleShader( strOpcodes, lstrlen(strOpcodes), 0, NULL, 
  351.         &m_pD3DXBufShader, &pBuffer );
  352.     if( FAILED(hr) )
  353.     {
  354.         if( pBuffer != NULL)
  355.         {
  356.             TCHAR* pstr;
  357.             TCHAR strOut[4096];
  358.             TCHAR* pstrOut;
  359.             // Need to replace \n with \r\n so edit box shows newlines properly
  360.             pstr = (TCHAR*)pBuffer->GetBufferPointer();
  361.             strOut[0] = _T('\0');
  362.             pstrOut = strOut;
  363.             for( int i = 0; i < 4096; i++ )
  364.             {
  365.                 if( *pstr == _T('\n') )
  366.                     *pstrOut++ = _T('\r');
  367.                 *pstrOut = *pstr;
  368.                 if( *pstr == _T('\0') )
  369.                     break;
  370.                 if( i == 4095 )
  371.                     *pstrOut = _T('\0');
  372.                 pstrOut++;
  373.                 pstr++;
  374.             }
  375.             // remove any blank lines at the end
  376.             while( strOut[lstrlen(strOut) - 1] == _T('\n') ||
  377.                    strOut[lstrlen(strOut) - 1] == _T('\r') )
  378.             {
  379.                 strOut[lstrlen(strOut) - 1] = _T('\0');
  380.             }
  381.             SetDlgItemText( IDC_COMPRESULT, strOut );
  382.             SAFE_RELEASE( pBuffer );
  383.         }
  384.         return hr;
  385.     }
  386.     else
  387.     {
  388.         SAFE_RELEASE( pBuffer );
  389.         // Delete old pixel shader
  390.         if( m_hPixelShader )
  391.             m_pd3dDevice->DeletePixelShader( m_hPixelShader );
  392.         m_hPixelShader = NULL;
  393.  
  394.         // Create new pixel shader
  395.         hr = m_pd3dDevice->CreatePixelShader( (DWORD*)m_pD3DXBufShader->GetBufferPointer(),
  396.                                               &m_hPixelShader );
  397.  
  398.         if( FAILED(hr) )
  399.         {
  400.             ((CStatic*)GetDlgItem(IDC_COMPRESULT))->SetWindowText( _T("Failure (D3D)"));
  401.             return hr;
  402.         }
  403.         else
  404.         {
  405.             ((CStatic*)GetDlgItem(IDC_COMPRESULT))->SetWindowText( _T("Success"));
  406.         }
  407.     }
  408.  
  409.     return S_OK;
  410. }
  411.  
  412.  
  413.  
  414.  
  415. //-----------------------------------------------------------------------------
  416. // Name: OneTimeSceneInit()
  417. // Desc: Called during initial app startup, this function performs all the
  418. //       permanent initialization.
  419. //-----------------------------------------------------------------------------
  420. HRESULT CAppForm::OneTimeSceneInit()
  421. {
  422.     return S_OK;
  423. }
  424.  
  425.  
  426.  
  427.  
  428. //-----------------------------------------------------------------------------
  429. // Name: FrameMove()
  430. // Desc: Called once per frame, the call is the entry point for animating
  431. //       the scene.
  432. //-----------------------------------------------------------------------------
  433. HRESULT CAppForm::FrameMove()
  434. {
  435.     // Move the camera along an ellipse
  436.     D3DXVECTOR3 from( 3*sinf(m_fTime/3), 3*cosf(m_fTime/3), 5.0f );
  437.     D3DXVECTOR3 at( 0.0f, 0.0f, 0.0f );
  438.     D3DXVECTOR3 up( 0.0f, 1.0f, 0.0f );
  439.  
  440.     D3DXMATRIX matWorld;
  441.     D3DXMatrixIdentity( &matWorld );
  442.     m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  443.  
  444.     D3DXMATRIX matView;
  445.     D3DXMatrixLookAtLH( &matView, &from, &at, &up );
  446.     m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  447.  
  448.     D3DXMATRIX matProj;
  449.     D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 0.5f, 1000.0f );
  450.     m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
  451.     return S_OK;
  452. }
  453.  
  454.  
  455.  
  456.  
  457. //-----------------------------------------------------------------------------
  458. // Name: Render()
  459. // Desc: Called once per frame, the call is the entry point for 3d
  460. //       rendering. This function sets up render states, clears the
  461. //       viewport, and renders the scene.
  462. //-----------------------------------------------------------------------------
  463. HRESULT CAppForm::Render()
  464. {
  465.     // Clear the viewport
  466.     m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0L );
  467.  
  468.     // Begin the scene
  469.     if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
  470.     {
  471.         // Set device state
  472.         m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
  473.         m_pd3dDevice->SetRenderState( D3DRS_CLIPPING, FALSE );
  474.         m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
  475.         m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,  FALSE );
  476.  
  477.         // Set the textures
  478.         m_pd3dDevice->SetTexture( 0, m_pTexture0 );
  479.         m_pd3dDevice->SetTexture( 1, m_pTexture1 );
  480.  
  481.         // Set the pixel shader constants
  482.         FLOAT fPixelShaderConstants[8][4] =
  483.         { //  Red  Green  Blue  Alpha
  484.             { 1.0f, 0.0f, 0.0f, 1.0f, },  // red
  485.             { 0.0f, 1.0f, 0.0f, 1.0f, },  // green
  486.             { 0.0f, 0.0f, 1.0f, 1.0f, },  // blue
  487.             { 1.0f, 1.0f, 0.0f, 1.0f, },  // yellow
  488.             { 0.0f, 1.0f, 1.0f, 1.0f, },  // cyan
  489.             { 1.0f, 0.0f, 1.0f, 1.0f, },  // purple
  490.             { 1.0f, 1.0f, 1.0f, 1.0f, },  // white
  491.             { 0.0f, 0.0f, 0.0f, 1.0f, },  // black
  492.         };
  493.         m_pd3dDevice->SetPixelShaderConstant( 0, (VOID*)fPixelShaderConstants, 8 );
  494.  
  495.         // Render the quad with the pixel shader
  496.         m_pd3dDevice->SetStreamSource( 0, m_pQuadVB, sizeof(CUSTOMVERTEX) );
  497.         m_pd3dDevice->SetVertexShader( D3DFVF_CUSTOMVERTEX );
  498.         m_pd3dDevice->SetPixelShader( m_hPixelShader );
  499.         m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
  500.  
  501.         // End the scene.
  502.         m_pd3dDevice->EndScene();
  503.     }
  504.  
  505.     return S_OK;
  506. }
  507.  
  508.  
  509.  
  510.  
  511. //-----------------------------------------------------------------------------
  512. // Name: InitDeviceObjects()
  513. // Desc: Initialize scene objects.
  514. //-----------------------------------------------------------------------------
  515. HRESULT CAppForm::InitDeviceObjects()
  516. {
  517.     HRESULT hr;
  518.  
  519.     // Create some textures
  520.     if( FAILED( D3DUtil_CreateTexture( m_pd3dDevice, _T("DX5_Logo.bmp"),
  521.                                        &m_pTexture0, D3DFMT_R5G6B5 ) ) )
  522.     {
  523.         return E_FAIL;
  524.     }
  525.  
  526.     if( FAILED( D3DUtil_CreateTexture( m_pd3dDevice, _T("Tree01S.tga"),
  527.                                        &m_pTexture1, D3DFMT_R5G6B5 ) ) )
  528.     {
  529.         return E_FAIL;
  530.     }
  531.  
  532.     // Create quad VB
  533.     hr = m_pd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX),
  534.                                            D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX,
  535.                                            D3DPOOL_MANAGED, &m_pQuadVB );
  536.     if( FAILED(hr) )
  537.         return hr;
  538.  
  539.     return S_OK;
  540. }
  541.  
  542.  
  543.  
  544.  
  545. //-----------------------------------------------------------------------------
  546. // Name: RestoreDeviceObjects()
  547. // Desc:
  548. //-----------------------------------------------------------------------------
  549. HRESULT CAppForm::RestoreDeviceObjects()
  550. {
  551.     HRESULT hr;
  552.  
  553.     // Fill the quad VB
  554.     CUSTOMVERTEX* pVertices = NULL;
  555.     hr = m_pQuadVB->Lock( 0, 4*sizeof(CUSTOMVERTEX), (BYTE**)&pVertices, 0 );
  556.     if( FAILED(hr) )
  557.         return hr;
  558.  
  559.     for( DWORD i=0; i<4; i++ )
  560.         pVertices[i] = g_Vertices[i];
  561.  
  562.     m_pQuadVB->Unlock();
  563.  
  564.     // Delete old pixel shader (redundant if InvalidateDeviceObjects is called first)
  565.     if( m_hPixelShader )
  566.         m_pd3dDevice->DeletePixelShader( m_hPixelShader );
  567.  
  568.     m_hPixelShader = NULL;
  569.  
  570.     // Create new pixel shader
  571.     if( m_pD3DXBufShader ) 
  572.         hr = m_pd3dDevice->CreatePixelShader( 
  573.                                  (DWORD*)m_pD3DXBufShader->GetBufferPointer(),
  574.                                  &m_hPixelShader );
  575.  
  576.     return S_OK;
  577. }
  578.  
  579.  
  580.  
  581.  
  582. //-----------------------------------------------------------------------------
  583. // Name: InvalidateDeviceObjects()
  584. // Desc: Called when the device-dependent objects are about to be lost.
  585. //-----------------------------------------------------------------------------
  586. HRESULT CAppForm::InvalidateDeviceObjects()
  587. {
  588.     if( m_hPixelShader )
  589.         m_pd3dDevice->DeletePixelShader( m_hPixelShader );
  590.     m_hPixelShader = NULL;
  591.  
  592.     return S_OK;
  593. }
  594.  
  595.  
  596.  
  597.  
  598. //-----------------------------------------------------------------------------
  599. // Name: DeleteDeviceObjects()
  600. // Desc: Called when the app is exiting, or the device is being changed,
  601. //       this function deletes any device dependent objects.
  602. //-----------------------------------------------------------------------------
  603. HRESULT CAppForm::DeleteDeviceObjects()
  604. {
  605.     SAFE_RELEASE( m_pTexture0 );
  606.     SAFE_RELEASE( m_pTexture1 );
  607.     SAFE_RELEASE( m_pQuadVB );
  608.     SAFE_RELEASE( m_pD3DXBufShader );
  609.     return S_OK;
  610. }
  611.  
  612.  
  613.  
  614.  
  615. //-----------------------------------------------------------------------------
  616. // Name: FinalCleanup()
  617. // Desc: Called before the app exits, this function gives the app the chance
  618. //       to cleanup after itself.
  619. //-----------------------------------------------------------------------------
  620. HRESULT CAppForm::FinalCleanup()
  621. {
  622.     return S_OK;
  623. }
  624.  
  625.  
  626.  
  627.  
  628. //-----------------------------------------------------------------------------
  629. // Name: ConfirmDevice()
  630. // Desc: Called during device intialization, this code checks the device
  631. //       for some minimum set of capabilities
  632. //-----------------------------------------------------------------------------
  633. HRESULT CAppForm::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior, D3DFORMAT Format )
  634. {
  635.     if( D3DSHADER_VERSION_MAJOR( pCaps->PixelShaderVersion ) < 1 )
  636.         return E_FAIL;
  637.  
  638.     return S_OK;
  639. }
  640.  
  641.  
  642.  
  643.  
  644.  
  645. //-----------------------------------------------------------------------------
  646. // The remaining code handles the UI for the MFC-based app.
  647. //-----------------------------------------------------------------------------
  648.  
  649.  
  650.  
  651.  
  652. //-----------------------------------------------------------------------------
  653. // Name: OnChangeDevice()
  654. // Desc: Use hit the "Change Device.." button. Display the dialog for the user
  655. //       to select a new device/mode, and call Change3DEnvironment to
  656. //       use the new device/mode.
  657. //-----------------------------------------------------------------------------
  658. VOID CAppForm::OnChangeDevice()
  659. {
  660.     UserSelectNewDevice();
  661.     GeneratePixelShaderOpcodes();
  662. }
  663.  
  664.  
  665.  
  666.  
  667. //-----------------------------------------------------------------------------
  668. // Name: OnToggleFullScreen()
  669. // Desc: Called when user toggles the fullscreen mode
  670. //-----------------------------------------------------------------------------
  671. void CAppForm::OnToggleFullScreen()
  672. {
  673.     ToggleFullscreen();
  674.     GeneratePixelShaderOpcodes();
  675. }
  676.  
  677.  
  678.  
  679.  
  680. //-----------------------------------------------------------------------------
  681. // Name: OnHScroll()
  682. // Desc: Called when the user moves any scroll bar. Check which scrollbar was
  683. //       moved, and extract the appropiate value to a global variable.
  684. //-----------------------------------------------------------------------------
  685. void CAppForm::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
  686. {
  687.     CFormView::OnHScroll(nSBCode, nPos, pScrollBar);
  688. }
  689.  
  690.  
  691.  
  692.  
  693. //-----------------------------------------------------------------------------
  694. // Name: UpdateUIForDeviceCapabilites()
  695. // Desc: Whenever we get a new device, call this function to enable/disable the
  696. //       appropiate UI controls to match the device's capabilities.
  697. //-----------------------------------------------------------------------------
  698. VOID CAppForm::UpdateUIForDeviceCapabilites()
  699. {
  700.     // Check the capabilities of the device
  701.  
  702.     // Update the UI checkbox states
  703. }
  704.  
  705.  
  706.  
  707.  
  708. //-----------------------------------------------------------------------------
  709. // Name: 
  710. // Desc: 
  711. //-----------------------------------------------------------------------------
  712. void CAppForm::OnPresets() 
  713. {
  714.     DWORD dwPreset = 0L;
  715.     dwPreset = ((CButton*)GetDlgItem(IDC_PRESET_0))->GetCheck() ? 0 : dwPreset;
  716.     dwPreset = ((CButton*)GetDlgItem(IDC_PRESET_1))->GetCheck() ? 1 : dwPreset;
  717.     dwPreset = ((CButton*)GetDlgItem(IDC_PRESET_2))->GetCheck() ? 2 : dwPreset;
  718.     dwPreset = ((CButton*)GetDlgItem(IDC_PRESET_3))->GetCheck() ? 3 : dwPreset;
  719.     dwPreset = ((CButton*)GetDlgItem(IDC_PRESET_4))->GetCheck() ? 4 : dwPreset;
  720.     dwPreset = ((CButton*)GetDlgItem(IDC_PRESET_5))->GetCheck() ? 5 : dwPreset;
  721.  
  722.     CEdit* pEdit = (CEdit*)GetDlgItem(IDC_INSTRUCTIONS);
  723.     pEdit->SetWindowText( g_strPixelShaderPresets[dwPreset] );
  724.  
  725.     // Generate the opcodes and pass them to the app
  726.     if( m_pd3dDevice != NULL )
  727.         GeneratePixelShaderOpcodes();
  728. }
  729.  
  730.  
  731.  
  732.  
  733.  
  734. //-----------------------------------------------------------------------------
  735. // Name: 
  736. // Desc: 
  737. //-----------------------------------------------------------------------------
  738. void CAppForm::GeneratePixelShaderOpcodes() 
  739. {
  740.     TCHAR strOpcodes[2048] = _T("");
  741.  
  742.     CEdit* pEdit = (CEdit*)GetDlgItem(IDC_INSTRUCTIONS);
  743.     pEdit->GetWindowText(strOpcodes, 2048);
  744.  
  745.     SetPixelShader( strOpcodes );
  746. }
  747.  
  748.  
  749.  
  750.  
  751. //-----------------------------------------------------------------------------
  752. // Name: 
  753. // Desc: 
  754. //-----------------------------------------------------------------------------
  755. void CAppForm::OnOpenPixelShaderFile() 
  756. {
  757.     ((CButton*)GetDlgItem(IDC_PRESET_0))->SetCheck( FALSE );
  758.     ((CButton*)GetDlgItem(IDC_PRESET_1))->SetCheck( FALSE );
  759.     ((CButton*)GetDlgItem(IDC_PRESET_2))->SetCheck( FALSE );
  760.     ((CButton*)GetDlgItem(IDC_PRESET_3))->SetCheck( FALSE );
  761.     ((CButton*)GetDlgItem(IDC_PRESET_4))->SetCheck( FALSE );
  762.     ((CButton*)GetDlgItem(IDC_PRESET_5))->SetCheck( FALSE );
  763.  
  764.  
  765.     static TCHAR g_strFileName[MAX_PATH] = _T("");
  766.     static TCHAR g_strInitialDir[MAX_PATH] = _T("");
  767.     TCHAR strFileName[MAX_PATH] = _T("");
  768.     TCHAR strBuffer[81];
  769.  
  770.     // Display the OpenFileName dialog. Then, try to load the specified file
  771.     OPENFILENAME ofn = { sizeof(OPENFILENAME), NULL, NULL,
  772.                          _T("Pixel Shader Text Files (.txt)\0*.txt\0\0"), 
  773.                          NULL, 0, 1, strFileName, MAX_PATH, g_strFileName, MAX_PATH, 
  774.                          g_strInitialDir, _T("Open Pixel Shader File"), 
  775.                          OFN_FILEMUSTEXIST, 0, 1, NULL, 0, NULL, NULL };
  776.  
  777.     if( FALSE == GetOpenFileName( &ofn ) )
  778.         return;
  779.     
  780.     FILE* file = fopen( strFileName, _T("r") );
  781.     if( file == NULL )
  782.         return;
  783.  
  784.     // Fill the list box with the preset's pixel shader instructions
  785.     CEdit* pEdit = (CEdit*)GetDlgItem(IDC_INSTRUCTIONS);
  786.     pEdit->SetSel(0, -1);
  787.     while( fgets( strBuffer, 80, file ) )
  788.     {
  789.         // Remove trailing newline char
  790.         if( strBuffer[max(1,strlen(strBuffer))-1] == '\n' )
  791.             strBuffer[max(1,strlen(strBuffer))-1] = '\0';
  792.         pEdit->ReplaceSel(strBuffer);
  793.         pEdit->ReplaceSel("\r\n");
  794.     }
  795.  
  796.     fclose(file);
  797.  
  798.     // Generater the opcodes and pass them to the app
  799.     GeneratePixelShaderOpcodes();
  800. }
  801.  
  802.  
  803. void CAppForm::OnChangeInstructions() 
  804. {
  805.     GeneratePixelShaderOpcodes();
  806. }
  807.